package Server;

/*
 * File:    GestorRecursos.java
 * Coms:    Implementa la gestión de las vallas
 */

/**
 * @author Daniel Cabrera Ebana - 686013
 * @author Alberto Sanchez Romero - 662385
 * @since 
 */

import java.util.ArrayList;

public class GestorRecursos {
	
	private ArrayList<String> imagenValla1 = new ArrayList<String>();
	private ArrayList<Integer> tiempoValla1 = new ArrayList<Integer>();
	private ArrayList<String> imagenValla2 = new ArrayList<String>();
	private ArrayList<Integer> tiempoValla2 = new ArrayList<Integer>();

	private int numClientes = 0;
	
	private boolean apagar = false;
	
	private int tiempoEnV1 = 0;	// tiempo que alguna imagen se encuentra en la
								// valla 1: valla activa
	private int tiempoEnV2 = 0;	// tiempo que alguna imagen se encuentra en la
								// valla 2: valla activa
	private int imgEnValla1 = 0;	// contador de numero de imagenes en la valla 1(0 ó 1)
	
	private int imgEnValla2 = 0;	// contador de numero de imagenes en la valla 2(0,1,2,3 ó 4)
	private int tiempoCola = 0;
	private int tmaxv2 = 0;
	private int difv2 = 0;
	private MonitorLabel1 monitorL1 = new MonitorLabel1();	// monitor para el Label 1
	private MonitorLabel2 monitorL2 = new MonitorLabel2();	// monitor para el Label 2

	boolean cerrarServidor=false;	// informa si hay que cerrar el servidor
	
	/**
	 * Constructor del monitor
	 */
	public GestorRecursos() {
	}

	/**
	 * Añadir una imagen a la cola de una valla
	 * Separa el nombre de la imagen y el tiempo y guarda cada uno en su respectivo ArrayList
	 * @param valla en la que se desea mostrar la imagen
	 * @param datos (URL,tiempo)
	 */
	synchronized void addcolaValla(int valla, String datos) {
		String imagen = datos.substring(0, datos.indexOf(","));
		int tiempo = Integer.parseInt(datos.substring(datos.indexOf(",") + 1));
		if (valla == 1) {
			imagenValla1.add(imagen);
			tiempoValla1.add(tiempo);
			monitorL1.addcolaValla();

		}
		if(valla==2){
			imagenValla2.add(imagen);
			tiempoValla2.add(tiempo);
			monitorL2.addcolaValla();
		}
			

	}

	/**
	 * Devuelve la primera imagen de la cola,(nombre,tiempo) y elemina ambos
	 * elementos de sus respectivas colas
	 * 
	 * @param valla
	 * @return nombre de la imagen,tiempo de visualización
	 */

	synchronized String getImg(int valla) {

		String nombreImagen = "";
		int tiempo = 0;

		if (valla == 1) {
			if (imagenValla1.size() > 0) {
				nombreImagen = imagenValla1.get(0);
			} else { // En caso de que no haya imagenes
				nombreImagen = "No hay imagenes";
			}
		} else {
			if (imagenValla2.size() > 0) {
				nombreImagen = imagenValla2.get(0);
			} else {
				nombreImagen = "No hay imagenes";
			}
		}
		if (valla == 1) {
			if (tiempoValla1.size() > 0) {
				tiempo = tiempoValla1.get(0);

			} else { // En caso de que no haya imagenes
				tiempo = 0;
			}
		} else {
			if (tiempoValla2.size() > 0) {
				tiempo = tiempoValla2.get(0);
			} else {
				tiempo = 0;
			}
		}
		// Eliminar la imagen que ya se está mostrando
		// (No se utiliza el método removeElementcolaValla() porque todo debe hacerse de una sola vez,
		// para evitar problemas de sincronización)
		if (valla == 1) {
			// Busca la posición de la imagen
			int indice = imagenValla1.indexOf(nombreImagen);

			// Si se encuentra la imagen en la cola
			if (indice >= 0) {
				// se recorre
				for (int i = indice; i < imagenValla1.size(); i++) {
					// Si no es el último elemento voy sobrescribiendo
					if (i < imagenValla1.size() - 1) {
						imagenValla1.set(i, imagenValla1.get(i + 1));
						tiempoValla1.set(i, tiempoValla1.get(i + 1));
					} else { // si es el último se elimina
						imagenValla1.remove(i);
						tiempoValla1.remove(i);
						monitorL1.quitacolaValla();
					}
				}
			}
		} else {
			int indice = imagenValla2.indexOf(nombreImagen);
			if (indice >= 0) {
				for (int i = indice; i < imagenValla2.size(); i++) {
					if (i < imagenValla2.size() - 1) {
						imagenValla2.set(i, imagenValla2.get(i + 1));
						tiempoValla2.set(i, tiempoValla2.get(i + 1));
					} else {
						imagenValla2.remove(i);
						tiempoValla2.remove(i);
						monitorL2.quitacolaValla();
					}
				}
			}
		}

		nombreImagen = nombreImagen + "," + tiempo;
		return nombreImagen;

	}

	/**
	 * Eliminar una imagen de la cola de una valla
	 * 
	 * @param valla
	 * @param imagen
	 *            que se desea eliminar
	 */
	synchronized void removeElementcolaValla(int valla, String imagen) {
		if (valla == 1) {
			// Busca la posición de la imagen
			int indice = imagenValla1.indexOf(imagen);
			// Si se encuentra la imagen en la cola
			if (indice >= 0) {
				// se recorre
				for (int i = indice; i < imagenValla1.size(); i++) {
					// System.out.println(i);
					// Si no es el último elemento voy sobrescribiendo
					if (i < imagenValla1.size() - 1) {
						imagenValla1.set(i, imagenValla1.get(i + 1));
						tiempoValla1.set(i, tiempoValla1.get(i + 1));
					} else { // si es el último se elimina
						imagenValla1.remove(i);
						tiempoValla1.remove(i);
					}
				}
			}
		} else {
			int indice = imagenValla2.indexOf(imagen);
			if (indice >= 0) {
				for (int i = indice; i < imagenValla2.size(); i++) {
					// System.out.println(i);
					if (i < imagenValla2.size() - 1) {
						imagenValla2.set(i, imagenValla2.get(i + 1));
						tiempoValla2.set(i, tiempoValla2.get(i + 1));
					} else {
						imagenValla2.remove(i);
						tiempoValla2.remove(i);
					}
				}
			}
		}
	}

	/**
	 * Devuelve el número de elementos en la cola de la valla
	 * 
	 * @param valla
	 * @return elementos en la cola
	 */
	synchronized int getsize(int valla) {
		if (valla == 1) {
			return imagenValla1.size();
		}
		return imagenValla2.size();
		
	}

	/**
	 * Calcula el tiempo estimado hasta que una imagen se vaya a mostrar
	 * 
	 * @param valla
	 * @param URL
	 *            de la imagen por la que se pregunta
	 * @return tiempo estimado de visualización
	 */
	synchronized int getTiempoEstimado(int valla, String URL) {
		int tiempoEstimado = 0;
		int posImagen = 0;
		if (valla == 1) {
			// Busca la posicion de la imagen
			posImagen = imagenValla1.indexOf(URL);
			// recorre solo hasta antes de donde se posiciona la imagen
			if (tiempoValla1.size() > 0) {
				for (int i = 0; i < posImagen; i++) {
					// va sumando los tiempos de las imagenes previas
					tiempoEstimado += tiempoValla1.get(i);
				}
			} else {
				tiempoEstimado = 0;
			}
		}
			posImagen = imagenValla2.indexOf(URL);
			if (tiempoValla2.size() > 0) {
				for (int i = 0; i < posImagen; i++) {
					tiempoEstimado += tiempoValla2.get(i);
				}
			} else {
				tiempoEstimado = 0;
			}
	
		if (tiempoEstimado < 0) {
			return 0;
		} else {
			return tiempoEstimado;
		}

	}

	// ------------metodos para el PanelInformacion ------------
	/**
	 * Añade un cliente al contador interno
	 */
	synchronized void addCliente() {
		numClientes++;
	}

	/**
	 * Elimina un cliente al contador interno
	 */
	synchronized void removeCliente() {
		if (numClientes > 0)
			numClientes--;
	}

	/**
	 * Devuelve el numero de clientesque hay conectados
	 * @return numClientes
	 */

	synchronized int getNumClientes() {
		return numClientes;
	}

	/**
	 * Modifica la variable que controla el apagado del servidor
	 */
	synchronized void setApagar() {
		apagar = true;
	}
	
	/**
	 * Devuelve el valor de la variable que controla el apagado el servidor
	 * @return apagar
	 */
	synchronized boolean getApagar() {
		return apagar;
	}
	
	/**
	 * Comprueba el tiempo estimado para que se muestren las imagenes que hay en la cola
	 * @param valla
	 * @return tiempoEstimado
	 */
	synchronized int tiempoEnCola(int valla) {

		int tiempoEstimado = 0;
		if (valla == 1) {

			// recorre solo hasta antes de donde se posiciona la imagen
			for (int i = 0; i < tiempoValla1.size(); i++) {
				// va sumando los tiempos de las imagenes previas
				tiempoEstimado += tiempoValla1.get(i);
			}
		} else {

			for (int i = 0; i < tiempoValla2.size(); i++) {
				tiempoEstimado += tiempoValla2.get(i);
			}

		}

		return tiempoEstimado;
	}

	// 

	/**
	 * Añade segundos al  contador interno de la Valla indicada, para saber cuanto tiempo estara activa 
	 * @param valla
	 * @param seg
	 */
	synchronized public void setAddSegundos(int valla, int seg) {
		if (valla == 1) {
			tiempoEnV1 = tiempoEnV1 + seg;
			imgEnValla1++;
		} else {
			tiempoEnV2 = tiempoEnV2 + seg;
			imgEnValla2++;
		}

	}

	// tiempo que la valla esta activa (mostrando una imagen)
	/**
	 * tiempo que la valla esta activa (mostrando imagenes )
	 * @param valla
	 * @return
	 */
	synchronized public int getTiempoValla(int valla) {
		if (valla == 1) {
			return tiempoEnV1;
		} else {
			return tiempoEnV2;
		}

	}

	// va restando "segundos" desde gestor recursos
	// al tiempo que va a estar la valla activa (con una imagen)
	// al tiempo "transcurrido" mostrando imagenes

	/**
	 * Actualiza el valor del contador interno que cada valla esta activa, decrementandole una unidad
	 * @param valla
	 */
	synchronized public void updateTimeOnValla(int valla) {

		if (valla == 1) {
			tiempoEnV1--;
			tmaxv2--;

		} else {
			tiempoEnV2--;
			tmaxv2--;

		}

	}

	// eliminar un elemento del contador numeroimagenes
	/**
	 * Elimina una unidad del contador que indica cuantas imagenes hay en la valla
	 * @param valla
	 */
	synchronized public void setMinusImgEnValla(int valla) {

		if (valla == 1) {
			if (imgEnValla1 > 0)
				imgEnValla1--;
		} else {
			if (imgEnValla2 > 0)
				imgEnValla2--;
		}

	}

	// devuelve el numero de imagenes que hay en cada valla
	// en la valla 1 devulve 0:1
	// en la valla 2 devuelve 0:1:2:3:4
	/**
	 * Devuelve el numero de imagenes que hay en cada valla
	 * @param valla
	 * @return
	 */
	synchronized public int getImgEnValla(int valla) {

		if (valla == 1) {
			return imgEnValla1;

		} else {
			return imgEnValla2;

		}

	}

	/**
	 * Actualiza el contador(restando un segundo) del tiempo que hay imagenes en cada cola, para el calculo del tiempo total 
	 * @param valla
	 */
	synchronized void updateTimeOnCola(int valla) {
		if (valla == 1) {
			tiempoCola--;

		} else {
			tiempoCola--;

		}

	}

	// saber cuantos segundos hay que añadir a tiempoEnvalla
	// para saber cuanto tiempo tiene que segir activa la valla

	/**
	 * Calcula el tiempo que hay que añadir al contador de la valla secundaria
	 * @param tmp
	 * @return
	 */
	synchronized int calcularTmp(int tmp) {

		if (tmaxv2 < tmp) {
			difv2 = tmp - tmaxv2;
			tmaxv2 = tmp;

		} else {
			difv2 = 0;
		}
		return (difv2);

	}

	/**
	 * Devuelve el monitor que gestion el thread(Label) de la Valla Principal 
	 * @return monitorL1
	 */
	synchronized MonitorLabel1 getMonitorL1() {
		return monitorL1;
	}

	/**
	 * Devuelve el monitor que gestion los thread(Label) de la Valla Secundaria 
	 * @return monitorL2
	 */
	synchronized MonitorLabel2 getMonitorL2() {

	return monitorL2;
	}
	
	/**
	 * Modifica la variable que indica si se debe cerrar el servidor
	 */
	synchronized void setCerrarServidor(){
		cerrarServidor = true;
	}
	/**
	 * @return Si el servidor debe ser cerrado
	 */
	synchronized boolean getCerrarServidor(){
		return cerrarServidor;
	}

}
